package com.atguigu.tingshu.album.service.impl;

import java.math.BigDecimal;
import java.util.*;

import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Maps;

import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.common.util.UploadFileUtil;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import com.tencentcloudapi.vod.v20180717.VodClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.stream.Collectors;

import static org.apache.coyote.http11.Constants.a;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;
	@Autowired
	private TrackStatMapper trackStatMapper;
	@Autowired
	private VodConstantProperties vodConstantProperties;
	@Autowired
	private VodUploadClient client;
	@Autowired
	private VodService vodService;
	@Autowired
	private AlbumInfoService albumInfoService;
	@Autowired
	private UserInfoFeignClient userInfoFeignClient;

	@Override
	public IPage<TrackListVo> findUserTrackPage(Integer pageNo, Integer pageSize, TrackInfoQuery trackInfoQuery) {
		IPage<TrackListVo> trackListVoIPage = new Page<>(pageNo, pageSize);
		trackInfoQuery.setUserId(AuthContextHolder.getUserId());
		trackListVoIPage = trackInfoMapper.findUserTrackPage(trackListVoIPage, trackInfoQuery);
		return trackListVoIPage;
	}

	@Override
	public UploadTrackVo uploadTrack(MultipartFile file) {
		UploadTrackVo uploadTrackVo = new UploadTrackVo();
		// 构造云点播请求对象
		VodUploadRequest request = new VodUploadRequest();
		// 将数据保存到临时地址并返回详细地址
		String uploadTempPath = UploadFileUtil.uploadTempPath(vodConstantProperties.getTempPath(), file);
		// 将临时地址传入云点播请求对象
		request.setMediaFilePath(uploadTempPath);
		// 设置云点播的媒体处理任务流
		request.setProcedure(vodConstantProperties.getProcedure());
		try {
			// 上传媒体文件到云点播并获取返回结果
			VodUploadResponse response = client.upload("ap-guangzhou", request);
			// 打印媒体ID
			log.info("Upload FileId = {}", response.getFileId());
			// 将返回信息封装卷到返回对象
			uploadTrackVo.setMediaFileId(response.getFileId());
			uploadTrackVo.setMediaUrl(response.getMediaUrl());
			return uploadTrackVo;
		} catch (Exception e) {
			e.printStackTrace();
			// 业务方进行异常处理
			log.error("Upload Err", e);
			return null;
		} finally {
			new File(uploadTempPath).delete();
		}
	}

	@Override
	@Transactional
	public void saveTrackInfo(TrackInfoVo trackInfoVo) {
		// 	1.保存基本信息
		TrackInfo trackInfo = new TrackInfo();
		BeanUtils.copyProperties(trackInfoVo, trackInfo);
		// 1.1 自定义数据
		trackInfo.setSource(SystemConstant.TRACK_SOURCE_UPLOAD);
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
		trackInfo.setUserId(AuthContextHolder.getUserId());
		// 1.2 查询顺序并设置最后的顺序
		TrackInfo dbTrackInfo = trackInfoMapper.selectOne(new LambdaQueryWrapper<TrackInfo>()
				.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
				.orderByDesc(TrackInfo::getOrderNum)
				.last("limit 1")
				.select(TrackInfo::getOrderNum));
		trackInfo.setOrderNum(dbTrackInfo.getOrderNum() + 1);
		// 1.3 媒体信息
		TrackMediaInfoVo trackMediaInfoVo = vodService.getTrackMediaInfo(trackInfo.getMediaFileId());
		trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfoVo.getDuration()));
		trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
		trackInfo.setMediaSize(trackMediaInfoVo.getSize());
		trackInfo.setMediaType(trackMediaInfoVo.getType());
		trackInfoMapper.insert(trackInfo);
		// 	2.初始化统计信息
		for (String s : List.of(SystemConstant.TRACK_STAT_PLAY, SystemConstant.TRACK_STAT_COLLECT, SystemConstant.TRACK_STAT_PRAISE, SystemConstant.TRACK_STAT_COMMENT)) {
			TrackStat trackStat = new TrackStat();
			trackStat.setTrackId(trackInfo.getId());
			trackStat.setStatType(s);
			trackStat.setStatNum(0);
			trackStatMapper.insert(trackStat);
		}
		// 	3.专辑包含声音数量 +1
		AlbumInfo albumInfo = albumInfoService.getById(trackInfo.getAlbumId());
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
		albumInfoService.updateById(albumInfo);
	}

	@Override
	@Transactional
	public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
		TrackInfo dbTrackInfo = trackInfoMapper.selectById(trackId);
		String dbTrackInfoMediaFileId = dbTrackInfo.getMediaFileId();
		String trackInfoVoMediaFileId = trackInfoVo.getMediaFileId();
		BeanUtils.copyProperties(trackInfoVo, dbTrackInfo);
		if (!dbTrackInfoMediaFileId.equals(trackInfoVoMediaFileId)) {
			TrackMediaInfoVo trackMediaInfoVo = vodService.getTrackMediaInfo(trackInfoVoMediaFileId);
			dbTrackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfoVo.getDuration()));
			dbTrackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
			dbTrackInfo.setMediaSize(trackMediaInfoVo.getSize());
			dbTrackInfo.setMediaType(trackMediaInfoVo.getType());
			vodService.removeTrack(dbTrackInfoMediaFileId);
		}
		trackInfoMapper.updateById(dbTrackInfo);
	}

	@Override
	public void removeTrackInfo(Long trackId) {
		// 	1.信息表查询信息
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		// 	2.信息表删除
		trackInfoMapper.deleteById(trackId);
		// 	3.统计表删除
		trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
		// 	4.专辑包含声音数 -1
		AlbumInfo albumInfo = albumInfoService.getById(trackInfo.getAlbumId());
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
		albumInfoService.updateById(albumInfo);
		// 	5.删除声音媒体
		vodService.removeTrack(trackInfo.getMediaFileId());
	}

	@Override
	public IPage<AlbumTrackListVo> findAlbumTrackPage(Long albumId, Integer pageNo, Integer pageSize) {
		IPage<AlbumTrackListVo> page = new Page<>(pageNo, pageSize);
		page = trackInfoMapper.findAlbumTrackPage(page, albumId);
		List<AlbumTrackListVo> records = page.getRecords();
		AlbumInfo albumInfo = albumInfoService.getById(albumId);
		// 用户是否登录
		Long userId = AuthContextHolder.getUserId();
		if (Objects.isNull(userId)) {
			// 	未登录,只能听免费声音和VIP或付费的试听集数
			if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
				this.setRecords(records, albumInfo);
			}
		} else {
			// 会员免费专辑
			if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
				// 	登录是否为会员
				UserInfo userInfo = userInfoFeignClient.findUserById(userId).getData();
				if (userInfo.getIsVip().equals(1)) {
					// 	会员是否过期
					// 会员过期了
					if (userInfo.getVipExpireTime().getTime() <= System.currentTimeMillis()) {
						this.setRecords(records, albumInfo);
					}
				}
			}
			// 是否为付费专辑
			else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
				// 	需要返回一个key是 TrackId 值是是否购买状态(0为未购买,1为购买)的 map
				List<Long> trackIdList = records
						.stream()
						.filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
						.map(AlbumTrackListVo::getTrackId)
						.collect(Collectors.toList());
				Map<Long, Integer> userIsPaidTrackMap = userInfoFeignClient.userIsPaidTrack(albumId, trackIdList).getData();
				records.stream()
						.filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
						.forEach(albumTrackListVo -> {
							Boolean isShowPaidMark = userIsPaidTrackMap.get(albumTrackListVo.getTrackId()).equals(0);
							albumTrackListVo.setIsShowPaidMark(isShowPaidMark);
						});
			}

		}
		return page;
	}


	/**
	 * 设置试听和非试听声音列表
	 *
	 * @param records   列表
	 * @param albumInfo 专辑信息
	 */
	private void setRecords(List<AlbumTrackListVo> records, AlbumInfo albumInfo) {
		records
				.stream()
				.filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
				.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
	}

	@Override
	public TrackStatVo getTrackStatVo(Long trackId) {
		return trackStatMapper.getTrackStatVo(trackId);
	}

	@Override
	public List<TrackPayVo> findUserTrackPaidList(Long trackId) {
		TrackInfo trackInfoCurrent = this.getById(trackId);
		Long albumId = trackInfoCurrent.getAlbumId();
		// 获取专辑信息
		AlbumInfo albumInfo = albumInfoService.getById(albumId);
		// 获取用户已购买的声音
		List<Long> userPaidIds = userInfoFeignClient.findUserPaidTrackList(albumId).getData();
		// 构造查询条件
		LambdaQueryWrapper<TrackInfo> trackInfoLambdaQueryWrapper = new LambdaQueryWrapper<TrackInfo>()
				.eq(TrackInfo::getAlbumId, albumId)
				.gt(TrackInfo::getOrderNum, trackInfoCurrent.getOrderNum());
		// 如果已购买的声音为空,就不拼接
		if (!CollectionUtils.isEmpty(userPaidIds))
			trackInfoLambdaQueryWrapper.notIn(TrackInfo::getId, userPaidIds);
		// 获取查询结果
		List<TrackInfo> trackInfos = trackInfoMapper.selectList(trackInfoLambdaQueryWrapper);
		// 转换成需购买的 声音Id 集合
		List<Long> noPaidIds = trackInfos.stream().map(TrackInfo::getId).collect(Collectors.toList());
		// 构造返回参数
		List<TrackPayVo> trackPayVoList = new ArrayList<>();
		// 获取需付费的专辑信息
		int count = noPaidIds.size();

		// 本集
		TrackPayVo currentTrackPayVo = new TrackPayVo();
		currentTrackPayVo.setPrice(albumInfo.getPrice());
		currentTrackPayVo.setName("本集");
		currentTrackPayVo.setTrackCount(0);
		trackPayVoList.add(currentTrackPayVo);

		// 后10集
		if (count > 0 && count <= 10) {
			TrackPayVo trackPayVoAfterTen = new TrackPayVo();
			trackPayVoAfterTen.setPrice(albumInfo.getPrice().multiply(new BigDecimal(count)));
			trackPayVoAfterTen.setName("后" + count + "集");
			trackPayVoAfterTen.setTrackCount(count);
			trackPayVoList.add(trackPayVoAfterTen);
		}

		// 处理超过10集的情况
		int i = 0;
		for (i = 10; i < count && i <= 50; i += 10) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo();
			trackPayVoAfterCount.setPrice(albumInfo.getPrice().multiply(new BigDecimal(i)));
			trackPayVoAfterCount.setName("后" + i + "集");
			trackPayVoAfterCount.setTrackCount(i);
			trackPayVoList.add(trackPayVoAfterCount);
		}
		// 跳出循环之后,0-10级前面处理过了,超过10级,但是小于50级的处理,最多购买50集
		if (count > 10 && count > (i - 10) && count <= 50) {
			TrackPayVo trackPayVoAfterFifty = new TrackPayVo();
			trackPayVoAfterFifty.setPrice(albumInfo.getPrice().multiply(new BigDecimal(count)));
			trackPayVoAfterFifty.setName("后" + count + "集");
			trackPayVoAfterFifty.setTrackCount(count);
			trackPayVoList.add(trackPayVoAfterFifty);
		}
		return trackPayVoList;
	}

	@Override
	public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		Long albumId = trackInfo.getAlbumId();
		List<TrackInfo> trackInfoList = new ArrayList<>();
		// 如果数量大于0,就是多集购买
		if (trackCount > 0) {
			// 获取用户已购买的本专几下声音的 Id 列表
			List<Long> userPaidIds = userInfoFeignClient.findUserPaidTrackList(albumId).getData();
			// 构造查询条件
			LambdaQueryWrapper<TrackInfo> trackInfoLambdaQueryWrapper = new LambdaQueryWrapper<TrackInfo>()
					.eq(TrackInfo::getAlbumId, albumId)
					.gt(TrackInfo::getOrderNum, trackInfo.getOrderNum())
					.orderByAsc(TrackInfo::getOrderNum)
					.last("limit "+trackCount);
			// 如果用户购买的声音 Id 列表不为空,就拼接条件,排除已购买的声音 Id
			if (!CollectionUtils.isEmpty(userPaidIds))
				trackInfoLambdaQueryWrapper.notIn(TrackInfo::getId, userPaidIds);
			// 进行查询
			trackInfoList = trackInfoMapper.selectList(trackInfoLambdaQueryWrapper);
		} else {
			// 否则是只买本集
			trackInfoList.add(trackInfo);
		}
		return trackInfoList;
	}
}

// 1253642698342284637